package messages

import (
	"encoding/binary"
	"io"
)

// 子消息接口
type Submessage interface {
	GetHeader() *SubmessageHeader
	Write(w io.Writer) error
	Read(r io.Reader) error
}

// InfoTimestamp子消息
type InfoTimestamp struct {
	Header    SubmessageHeader
	Timestamp Time
}

func (it *InfoTimestamp) GetHeader() *SubmessageHeader {
	return &it.Header
}

func (it *InfoTimestamp) Write(w io.Writer) error {
	return binary.Write(w, binary.BigEndian, it.Timestamp)
}

func (it *InfoTimestamp) Read(r io.Reader) error {
	return binary.Read(r, binary.BigEndian, &it.Timestamp)
}

// InfoDestination子消息
type InfoDestination struct {
	Header     SubmessageHeader
	GUIDPrefix [12]byte
}

func (id *InfoDestination) GetHeader() *SubmessageHeader {
	return &id.Header
}

func (id *InfoDestination) Write(w io.Writer) error {
	_, err := w.Write(id.GUIDPrefix[:])
	return err
}

func (id *InfoDestination) Read(r io.Reader) error {
	_, err := r.Read(id.GUIDPrefix[:])
	return err
}

// Data子消息
type Data struct {
	Header            SubmessageHeader
	ExtraFlags        uint16
	OctetsToInlineQos uint16
	ReaderID          EntityID
	WriterID          EntityID
	WriterSN          SequenceNumber
	SerializedData    []byte
}

func (d *Data) GetHeader() *SubmessageHeader {
	return &d.Header
}

func (d *Data) Write(w io.Writer) error {
	if err := binary.Write(w, binary.BigEndian, d.ExtraFlags); err != nil {
		return err
	}
	if err := binary.Write(w, binary.BigEndian, d.OctetsToInlineQos); err != nil {
		return err
	}
	if err := d.ReaderID.Write(w); err != nil {
		return err
	}
	if err := d.WriterID.Write(w); err != nil {
		return err
	}
	if err := d.WriterSN.Write(w); err != nil {
		return err
	}
	_, err := w.Write(d.SerializedData)
	return err
}

func (d *Data) Read(r io.Reader) error {
	if err := binary.Read(r, binary.BigEndian, &d.ExtraFlags); err != nil {
		return err
	}
	if err := binary.Read(r, binary.BigEndian, &d.OctetsToInlineQos); err != nil {
		return err
	}
	if err := d.ReaderID.Read(r); err != nil {
		return err
	}
	if err := d.WriterID.Read(r); err != nil {
		return err
	}
	if err := d.WriterSN.Read(r); err != nil {
		return err
	}

	// 读取序列化数据
	dataLen := int(d.Header.SubmessageLength) - 16 // 减去固定字段长度
	d.SerializedData = make([]byte, dataLen)
	_, err := r.Read(d.SerializedData)
	return err
}

// Heartbeat子消息
type Heartbeat struct {
	Header   SubmessageHeader
	ReaderID EntityID
	WriterID EntityID
	FirstSN  SequenceNumber
	LastSN   SequenceNumber
	Count    uint32
}

func (h *Heartbeat) GetHeader() *SubmessageHeader {
	return &h.Header
}

func (h *Heartbeat) Write(w io.Writer) error {
	if err := h.ReaderID.Write(w); err != nil {
		return err
	}
	if err := h.WriterID.Write(w); err != nil {
		return err
	}
	if err := h.FirstSN.Write(w); err != nil {
		return err
	}
	if err := h.LastSN.Write(w); err != nil {
		return err
	}
	return binary.Write(w, binary.BigEndian, h.Count)
}

func (h *Heartbeat) Read(r io.Reader) error {
	if err := h.ReaderID.Read(r); err != nil {
		return err
	}
	if err := h.WriterID.Read(r); err != nil {
		return err
	}
	if err := h.FirstSN.Read(r); err != nil {
		return err
	}
	if err := h.LastSN.Read(r); err != nil {
		return err
	}
	return binary.Read(r, binary.BigEndian, &h.Count)
}

// 实体ID
type EntityID struct {
	EntityKey  [3]byte
	EntityKind uint8
}

func (e *EntityID) Write(w io.Writer) error {
	if _, err := w.Write(e.EntityKey[:]); err != nil {
		return err
	}
	return binary.Write(w, binary.BigEndian, e.EntityKind)
}

func (e *EntityID) Read(r io.Reader) error {
	if _, err := r.Read(e.EntityKey[:]); err != nil {
		return err
	}
	return binary.Read(r, binary.BigEndian, &e.EntityKind)
}

// 序列号
type SequenceNumber struct {
	High int32
	Low  uint32
}

func (sn *SequenceNumber) Write(w io.Writer) error {
	if err := binary.Write(w, binary.BigEndian, sn.High); err != nil {
		return err
	}
	return binary.Write(w, binary.BigEndian, sn.Low)
}

func (sn *SequenceNumber) Read(r io.Reader) error {
	if err := binary.Read(r, binary.BigEndian, &sn.High); err != nil {
		return err
	}
	return binary.Read(r, binary.BigEndian, &sn.Low)
}

// 时间戳
type Time struct {
	Seconds  int32
	Fraction uint32
}

// AckNack子消息
type AckNack struct {
	Header   SubmessageHeader
	ReaderID EntityID
	WriterID EntityID
	ReaderSN SequenceNumber
	Count    uint32
	Bitmap   []byte
}

func (an *AckNack) GetHeader() *SubmessageHeader {
	return &an.Header
}

func (an *AckNack) Write(w io.Writer) error {
	if err := an.ReaderID.Write(w); err != nil {
		return err
	}
	if err := an.WriterID.Write(w); err != nil {
		return err
	}
	if err := an.ReaderSN.Write(w); err != nil {
		return err
	}
	if err := binary.Write(w, binary.BigEndian, an.Count); err != nil {
		return err
	}

	// 写入位图长度和内容
	bitmapLen := uint32(len(an.Bitmap))
	if err := binary.Write(w, binary.BigEndian, bitmapLen); err != nil {
		return err
	}
	if _, err := w.Write(an.Bitmap); err != nil {
		return err
	}

	return nil
}

func (an *AckNack) Read(r io.Reader) error {
	if err := an.ReaderID.Read(r); err != nil {
		return err
	}
	if err := an.WriterID.Read(r); err != nil {
		return err
	}
	if err := an.ReaderSN.Read(r); err != nil {
		return err
	}
	if err := binary.Read(r, binary.BigEndian, &an.Count); err != nil {
		return err
	}

	// 读取位图长度和内容
	var bitmapLen uint32
	if err := binary.Read(r, binary.BigEndian, &bitmapLen); err != nil {
		return err
	}
	an.Bitmap = make([]byte, bitmapLen)
	_, err := r.Read(an.Bitmap)
	return err
}
